使用 signal

中断处理是操作系统和系统软件的关键部分. Unix 中的软件中断被称为信号 (signals)

早期的信号处理机制

各种事件促使内核向进程发送信号. 这些事件包括用户的击键、进程的非法操作和计 时器到时. 一个进程调用 signal 在以下3种处理信号的方法中选择

  1. 默认操作(一般是终止进程), 比如, signal(SIGALRM, SIG_DFL)
  2. 忽略信号, 比如, signal(SIGALRM, SIG_IGN)
  3. 调用一个函数, 比如, signal(SIGALRM, handler)

处理多个信号

如果只有一个信号要处理, 原始的信号处理模型足以应付, 如果有多个信号到达会发生什么事情?

信号处理2: sigaction

在 POSIX 中用 sigaction 替代 signal. 参数非常相似. 指定什么信号将被如何处 理. 如果愿意还能得到这个信号上一次被处理时的设置.

int sigaction(signalnumber, action, prevaction)
  sigaction
目标 指定一个信号处理函数
头文件 #include <signal.h>
原型 res = sigaction(int signum, const struct sigaction * action, struct sigaction *prevaction);
参数 signum 要处理的信号, action 指针, 指向描述操作的结构, prevaction 指向被替换操作的结构
返回值 -1 error, 0 success

关于 struct sigaction 的定义如下

struct sigaction{
    /* set only one of these two */
    void (*sa_handler)();   /* SIG_DFL, SIG_IGN or function */
    void (*sa_sigaction)(int, siginfo_t *, void *); /* new handler */

    sigset_t sa_mast;       /* signals to block while handling */
    int sa_flags;           /* enable various behaviros */
}

sa_handler or sa_sigaction

如果老的处理方式(即SIG_DFL, SIG_IGN 或者处理函数)就够用来额, 那么可以设置 sa_handler 为其中之一, 旧的信号处理方式, 只能得到信号编号.

否则, 如果设定 sa_sigaction 为一个处理函数, 那么那个处理函数被调用的时候, 不但可以得到信号编号而且可以获悉被调用的原因以及产生问题的上下文的相关信息

需要设置 sa_flags 的 SA_SIGINFO 位告知内核使用新的信号处理方式.

sa_flags

标记 含义
SA_RESETHAND 当处理函数被调用时重置. 也就是蚕蛹捕鼠器模式
SA_NODEFER 当处理信号时关闭信号自动阻塞. 这样就允许递给调用信号处理函数
SA_RESTART 当系统调用是针对一些慢速的设备或类似的系统调用, 重新开始, 而不是返回. 这样是采用BSD模式
SA_SIGINFO 指名使用 sa_sigaction 的处理函数的值. 如果这个位没有被设置, 那么久就使用 sa_handler 指向的处理函数的值. 如果 sa_sigaction 被使用, 传递给处理函数的不只是信号编号, 还包括指向描述信号产生原因和条件的结构体

sa_mask

sa_mask 决定处理一个消息时是否要阻塞其他信号. 参下章

例子: 使用 sigaction